package com.net.xpay.operator.controller.operator;

import com.google.common.base.Strings;
import com.net.xpay.operator.secutiry.RequestUser;
import com.net.xpay.operator.vo.*;
import com.net.common.exception.BusinessException;
import com.net.common.model.ResultData;
import com.net.common.model.ResultList;
import com.net.common.util.LocalDateUtil;
import com.net.common.util.PhoneUtil;
import com.net.xpay.common.domain.CheckCode;
import com.net.xpay.common.domain.User;
import com.net.xpay.common.domain.UserShard;
import com.net.xpay.common.domain.operator.OperatorUser;
import com.net.xpay.common.domain.operator.OperatorUserBinding;
import com.net.xpay.common.domain.stat.UserRealTimeStat;
import com.net.xpay.common.enums.user.CheckCodeType;
import com.net.xpay.common.helper.RedisHelper;
import com.net.xpay.common.manager.CheckCodeManager;
import com.net.xpay.common.manager.UserManager;
import com.net.xpay.common.manager.UserShardManager;
import com.net.xpay.common.manager.operator.OperatorUserBindingManager;
import com.net.xpay.common.manager.operator.OperatorUserManager;
import com.net.xpay.common.manager.stat.UserDailyStatManager;
import com.net.xpay.common.manager.stat.UserRealTimeStatManager;
import com.net.xpay.common.model.AddOperatorUserModel;
import com.net.xpay.common.model.AggOperatorUserDailyStatModel;
import com.net.xpay.common.model.PasswordModel;
import com.net.xpay.common.model.search.OperatorUsersSearchModel;
import com.net.xpay.common.service.UserRealTimeStatService;
import com.net.xpay.common.validator.CheckCodeValidator;
import com.net.xpay.core.constant.PoseidonErrorCode;
import com.net.xpay.core.constant.RedisKey;
import com.net.xpay.core.domain.UserAccount;
import com.net.xpay.core.manager.UserAccountManager;
import com.net.xpay.core.utils.BeanCopierUtil;
import com.net.xpay.operator.vo.*;
import com.net.shard.ShardUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

@RestController
@RequestMapping("/operator/operator-user")
@Api(tags = "操盘手/基本信息", description = "操盘手 基本信息 net")
public class OperatorUserController {

    private static final int MAX_PASS_LENGTH = 20; //最大的密码长度
    private static final int MIN_PASS_LENGTH = 6; //最小的密码长度

    @Autowired
    private OperatorUserBindingManager operatorUserBindingManager;

    @Autowired
    private UserManager userManager;

    @Autowired
    private OperatorUserManager operatorUserManager;

    @Autowired
    private UserDailyStatManager userDailyStatManager;

    @Autowired
    private UserRealTimeStatManager userRealTimeStatManager;

    @Autowired
    private UserAccountManager userAccountManager;

    @Autowired
    private CheckCodeManager checkCodeManager;

    @Autowired
    private CheckCodeValidator checkCodeValidator;

    @Autowired
    private UserShardManager userShardManager;

    @Autowired
    private UserRealTimeStatService userRealTimeStatService;

    @Autowired
    private RedisHelper redisHelper;




    @ApiOperation("获取用户名称")
    @PostMapping("/get-user-info")
    @ResponseBody
    public ResultData<String> getUserInfo(@RequestBody AddOperatorUserModel model) {
        if (Strings.isNullOrEmpty(model.getMobile())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "手机号不能为空");
        }
        //验证手机号
        if (!PhoneUtil.isEffectiveMobile(model.getMobile())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "手机号格式不正确");
        }
        User user = userManager.findByMobile(model.getMobile());
        if (user == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "公司商户账号未注册");
        }
        if (user.getName() == null) {
            return new ResultData<>("-");
        }

        return new ResultData<>(user.getName());
    }

    /**
     * 获取操盘手信息
     */
    @ApiOperation("获取操盘手信息")
    @GetMapping("/info")
    public ResultData<OperatorUserVo> getOperatorUserInfo(@ApiIgnore @RequestUser OperatorUser operatorUser) {
        OperatorUserVo vo = new OperatorUserVo();
        BeanCopierUtil.copy(operatorUser, vo);

        Long count = operatorUserBindingManager.byOperatorUserIdCount(operatorUser.getId());
        vo.setCompanyCount(count);
        return new ResultData<>(vo);
    }


    @ApiOperation("搜索关联公司信息(昨日，近7天，近1个月)")
    @PostMapping("/binding-user-list")
    @ResponseBody
    public ResultList<OperatorUserStatListVo> bindingUserList(@ApiIgnore @RequestUser OperatorUser operatorUser, @RequestBody OperatorUsersSearchModel searchModel) {
        if (searchModel.getStartDay() == null && searchModel.getEndDay() == null){
            if (searchModel.getDataType() == 1) {
                searchModel.setDay(LocalDate.now().minusDays(1L));
            }
            if (searchModel.getDataType() == 2) {
                searchModel.setStartDay(LocalDate.now().minusDays(7L));
                searchModel.setEndDay(LocalDate.now().minusDays(1L));
            }
            if (searchModel.getDataType() == 3) {
                searchModel.setStartDay(LocalDateUtil.getMonthStartDay(LocalDate.now().minusMonths(1L)));
                searchModel.setEndDay(LocalDate.now().minusDays(1L));
            }
        }

        List<OperatorUserBinding> list = operatorUserBindingManager.getByOperatorIdList(operatorUser.getId());
        List<OperatorUserStatListVo> vos = BeanCopierUtil.batchCopy(OperatorUserBinding.class, OperatorUserStatListVo.class, list);
        //汇总数据
        long ouTransCount = 0L;
        BigDecimal ouTransAmount = new BigDecimal("0");

        long ouSuccessTransCount = 0L;
        BigDecimal ouSuccessTransAmount = new BigDecimal("0");

        BigDecimal ouServicePrice = new BigDecimal("0");
        BigDecimal ouMoneyLeft = new BigDecimal("0");

        for (OperatorUserStatListVo vo : vos) {
            try {
                User user = userManager.getById(vo.getUserId());
                UserShard userShard = userShardManager.getById(user.getId());
                ShardUtil.setShardContext(userShard.getShardId());
                if (!Strings.isNullOrEmpty(searchModel.getName())) {
                    if (!user.getName().contains(searchModel.getName())) {
                        continue;
                    }
                }
                vo.setName(user.getName());
                //状态
                vo.setSecurityStatus(user.getSecurityStatus());
                //服务费余额

                UserAccount userAccount = userAccountManager.getById(vo.getUserId());
                vo.setMoneyLeft(userAccount.getMoneyLeft());

                ouMoneyLeft = ouMoneyLeft.add(new BigDecimal(userAccount.getMoneyLeft()).multiply(new BigDecimal("0.01")).setScale(2, RoundingMode.HALF_UP));

                AggOperatorUserDailyStatModel model = userDailyStatManager.sumByUserIdAndSearchModel(vo.getUserId(), searchModel);
                if (model == null) {

                    continue;
                }
                vo.setTotalCount(model.getTotalCount());
                vo.setTotalTransAmount(model.getTotalTransAmount());
                vo.setTotalSuccessCount(model.getTotalSuccessCount());
                vo.setTotalSuccessTransAmount(model.getTotalSuccessTransAmount());
                vo.setTotalServicePrice(model.getTotalServicePrice());


                ouTransCount = ouTransCount + model.getTotalCount();
                ouTransAmount = ouTransAmount.add(model.getTotalTransAmount());
                ouSuccessTransCount = ouSuccessTransCount + model.getTotalSuccessCount();
                ouSuccessTransAmount = ouSuccessTransAmount.add(model.getTotalSuccessTransAmount());

                ouServicePrice = ouServicePrice.add(model.getTotalServicePrice());
            } finally {
                ShardUtil.cleanShardContext();
            }
        }

        ResultList<OperatorUserStatListVo> resultList = new ResultList<>(vos);
        //汇总数据
        OperatorUserSumListVo sumListVo = new OperatorUserSumListVo();
        sumListVo.setCompanyCount(vos.size());
        sumListVo.setTotalCount(ouTransCount);
        sumListVo.setTotalSuccessCount(ouSuccessTransCount);
        sumListVo.setTotalTransAmount(ouTransAmount);
        sumListVo.setTotalSuccessTransAmount(ouSuccessTransAmount);
        sumListVo.setTotalServicePrice(ouServicePrice);
        sumListVo.setMoneyLeft(ouMoneyLeft);

        resultList.setExtra(sumListVo);

        return resultList;
    }

    @ApiOperation("搜索关联公司信息(实时)")
    @PostMapping("/real-time-binding-user-list")
    @ResponseBody
    public ResultList<OperatorUserRealTimeStatListVo> realTimeBindingUserList(@ApiIgnore @RequestUser OperatorUser operatorUser, @RequestBody OperatorUsersSearchModel searchModel) {
        searchModel.setStartDay(LocalDateUtil.getDayStart(LocalDate.now()).toLocalDate());
        List<OperatorUserBinding> list = operatorUserBindingManager.getByOperatorIdList(operatorUser.getId());

        List<OperatorUserRealTimeStatListVo> vos = BeanCopierUtil.batchCopy(OperatorUserBinding.class, OperatorUserRealTimeStatListVo.class, list);
        //汇总数据
        long ouTransCount = 0L;
        BigDecimal ouTransAmount = new BigDecimal("0");

        long ouSuccessTransCount = 0L;
        BigDecimal ouSuccessTransAmount = new BigDecimal("0");

        BigDecimal ouServicePrice = new BigDecimal("0");
        BigDecimal ouMoneyLeft = new BigDecimal("0");

        LocalDateTime ouUpdateTime = null;

        for (OperatorUserRealTimeStatListVo vo : vos) {
            try {
                User user = userManager.getById(vo.getUserId());
                UserShard userShard = userShardManager.getById(user.getId());
                ShardUtil.setShardContext(userShard.getShardId());
                if (!Strings.isNullOrEmpty(searchModel.getName())) {
                    if (!user.getName().contains(searchModel.getName())) {
                        continue;
                    }
                }
                vo.setName(user.getName());
                //状态
                vo.setSecurityStatus(user.getSecurityStatus());
                //服务费余额
                UserAccount userAccount = userAccountManager.getById(vo.getUserId());
                vo.setMoneyLeft(userAccount.getMoneyLeft());
                ouMoneyLeft = ouMoneyLeft.add(new BigDecimal(userAccount.getMoneyLeft()).multiply(new BigDecimal("0.01")).setScale(2, RoundingMode.HALF_UP));

                UserRealTimeStat userRealTimeStat = userRealTimeStatManager.getByUserId(vo.getUserId());
                if (userRealTimeStat == null) {
                    continue;
                }
                vo.setTotalCount(userRealTimeStat.getTotalCount());
                vo.setTotalTransAmount(userRealTimeStat.getTotalTransAmount());
                vo.setTotalSuccessCount(userRealTimeStat.getTotalSuccessCount());
                vo.setTotalSuccessTransAmount(userRealTimeStat.getTotalSuccessTransAmount());
                vo.setTotalServicePrice(userRealTimeStat.getTotalServicePrice());


                ouTransCount = ouTransCount + userRealTimeStat.getTotalCount();
                ouTransAmount = ouTransAmount.add(userRealTimeStat.getTotalTransAmount());
                ouSuccessTransCount = ouSuccessTransCount + userRealTimeStat.getTotalSuccessCount();
                ouSuccessTransAmount = ouSuccessTransAmount.add(userRealTimeStat.getTotalSuccessTransAmount());

                ouServicePrice = ouServicePrice.add(userRealTimeStat.getTotalServicePrice());

                ouUpdateTime = userRealTimeStat.getUpdateTime();
            } finally {
                ShardUtil.cleanShardContext();
            }

        }
        ResultList<OperatorUserRealTimeStatListVo> resultList = new ResultList<>(vos);

        //汇总数据
        OperatorUserRealTimeSumListVo sumListVo = new OperatorUserRealTimeSumListVo();
        sumListVo.setCompanyCount(vos.size());
        sumListVo.setTotalCount(ouTransCount);
        sumListVo.setTotalSuccessCount(ouSuccessTransCount);
        sumListVo.setTotalTransAmount(ouTransAmount);
        sumListVo.setTotalSuccessTransAmount(ouSuccessTransAmount);
        sumListVo.setTotalServicePrice(ouServicePrice);
        sumListVo.setMoneyLeft(ouMoneyLeft);
        sumListVo.setUpdateTime(ouUpdateTime);


        resultList.setExtra(sumListVo);
        return resultList;
    }

    @ApiOperation("实时刷新")
    @PostMapping("/real-time-refresh")
    @ResponseBody
    public ResultData<Boolean> realTimeRefresh(@ApiIgnore @RequestUser OperatorUser operatorUser) {

        String strLimit = RedisKey.USER_REAL_TIME_STAT_REFRESH + operatorUser.getId();

        if (redisHelper.get(strLimit) == null){
            redisHelper.set(strLimit, operatorUser.getId(),10L);
            List<OperatorUserBinding> list = operatorUserBindingManager.getByOperatorIdList(operatorUser.getId());
            if (list.size() == 0){
                return new ResultData<>(true);
            }
            for (OperatorUserBinding operatorUserBinding : list) {

                //实时统计
                userRealTimeStatService.doUserRealTimeStat(operatorUserBinding.getUserId(),LocalDateTime.now());
            }
            return new ResultData<>(true);
        }else {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "10s后可刷新");
        }


    }


    @ApiOperation(value = "修改密码（登录后才能操作）")
    @PostMapping("/modify-password")
    public ResultData<Boolean> modifyPassword(@ApiIgnore @RequestUser OperatorUser operator, @RequestBody PasswordModel passwordModel) {
        if (operator == null) {
            throw new BusinessException(PoseidonErrorCode.NEED_LOGIN, "请先登录,登陆之后才能修改密码");
        }
        if (Strings.isNullOrEmpty(passwordModel.getPassword())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "新密码不能为空");
        }
        if (Strings.isNullOrEmpty(passwordModel.getRepeatPassword())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "再次输入的新密码不能为空");
        }
        if (!passwordModel.getPassword().equals(passwordModel.getRepeatPassword())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "两次输入的新密码不一样");
        }
        if (passwordModel.getPassword().length() > MAX_PASS_LENGTH || passwordModel.getPassword().length() < MIN_PASS_LENGTH) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "密码长度必须在6到20个字符");
        }
        if (Strings.isNullOrEmpty(passwordModel.getCheckCode())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "验证码不能为空");
        }
        //验证验证码
        CheckCode checkCode = checkCodeManager.findByMobileAndType(operator.getMobile(), CheckCodeType.OPERATOR_USER_MODIFY_PASSWORD);
        checkCodeValidator.validateCheckCode(checkCode, passwordModel.getCheckCode());

        operator.setPassword(BCrypt.hashpw(passwordModel.getPassword(), BCrypt.gensalt()));
        operatorUserManager.updateByPrimaryKeyWithVersion(operator);
        return new ResultData<>(true);
    }


}
